package main

import (
	"bufio"
	"crypto/tls"
	"fmt"
	"log"
	"net"

	"github.com/spf13/viper"
)

var (
	v *viper.Viper
)

type SSLServerConfig struct {
	CertFile  string
	CertChain string
	KeyFile   string
}

func init() {
	v = viper.GetViper()
	v.SetConfigFile("demo_tls_server.json")
	v.SetConfigType("json")
	v.AddConfigPath("/etc/demo_tls_server")
	v.AddConfigPath("$Home/demo_tls_server")
	v.AddConfigPath(".")
}

func main() {
	print("这是运行TLS的服务器程序!\n")
	// 加载服务器的配置
	cfg := &SSLServerConfig{}
	err := v.ReadInConfig()
	if err != nil {
		fmt.Println("加载配置时发生了错误:", err)
		return
	}
	if err = v.Unmarshal(cfg); err != nil {
		fmt.Println("反序列化配置错误：", err)
	}
	fmt.Println("配置:", cfg)

	// 配置tls证书
	cert, err := tls.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile)
	if err != nil {
		log.Println("在加载证书时发现错误", err)
		return
	}
	config := &tls.Config{Certificates: []tls.Certificate{cert}}
	// 应用运行在0.0.0.0:443
	service, err := tls.Listen("tcp", ":4210", config)
	if err != nil {
		log.Println(err)
		return
	}
	defer service.Close()
	// 等待客户端的连接，连接上以后用runtine:handleConn来处理业务逻辑
	for {
		conn, err := service.Accept()
		if err != nil {
			log.Println(err)
			continue
		}
		go handleConn(conn)
	}
}

// 客户端连接后，调用这个go runtine来处理实际业务。
// 在下面的示例中，它总是返回"200 OK\r\n"
func handleConn(conn net.Conn) {
	defer conn.Close()
	r := bufio.NewReader(conn)
	for {
		msg, err := r.ReadString('\n')
		if err != nil {
			log.Println(err)
			return
		}
		println(msg)
		n, err := conn.Write([]byte("200 OK\r\n"))
		if err != nil {
			log.Println(n, err)
			return
		}
	}
}
